package cn.tworice.generate.service.impl;

import cn.tworice.common.util.StringUtils;
import cn.tworice.generate.constant.CodeGenConst;
import cn.tworice.generate.service.CodeGenerationService;
import cn.tworice.generate.util.CodeUtils;
import cn.tworice.generate.vo.CreateServerVO;
import cn.tworice.generate.vo.Parameter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class DefaultCodeGenerationServiceImpl implements CodeGenerationService {

    @Resource
    private CodeUtils codeUtil;

    private final List<String> ignoreField = new ArrayList<>();

    @PostConstruct
    public void initIgnoreField(){
        this.ignoreField.add("id");
        this.ignoreField.add("create_time");
        this.ignoreField.add("update_time");
        this.ignoreField.add("creator");
        this.ignoreField.add("deleted");
    }

    /**
     * 构建Web Client文件
     * @param createServerVO 参数
     * @return boolean
     **/
    @Override
    public boolean createClient(CreateServerVO createServerVO) {
        try{
            String content = codeUtil.readByName("client");
            content = content.replace(CodeGenConst.ENTITY_NAME, createServerVO.getEntityName());
            StringBuilder clientHeader = new StringBuilder();
            clientHeader.append("@RestController\r\n");
            clientHeader.append("@RequestMapping(\"");
            clientHeader.append(createServerVO.getUrl());
            clientHeader.append("\")\r\n");
            clientHeader.append("@CrossOrigin\r\n");
            clientHeader.append("@Log(table = \"");
            clientHeader.append(createServerVO.getTableName());
            clientHeader.append("\")\r\n");
            clientHeader.append("@Api(tags = \"");
            clientHeader.append(createServerVO.getTableComment());
            clientHeader.append("\")\r\n");
            content = content.replace(CodeGenConst.CLIENT_HEADER, clientHeader.toString());
            codeUtil.createFile(codeUtil.getAdminProjectPath() + "\\src\\main\\java\\cn\\tworice\\client\\web\\" + createServerVO.getEntityName() + "Client.java", content);
            log.info("生成Client文件成功");
        }catch (Exception exception){
            log.error("生成Client文件失败",exception);
            return false;
        }

        return true;
    }

    @Override
    public boolean createService(CreateServerVO createServerVO) {
        try{
            StringBuilder builder = new StringBuilder();
            String templateContent = codeUtil.readByName("service");
            templateContent = templateContent.replace(CodeGenConst.ENTITY_NAME, createServerVO.getEntityName());
            templateContent = templateContent.replace(CodeGenConst.QUERY, this.buildQuery(createServerVO));
            int serviceEndIndex = templateContent.indexOf("@Service") + 8;
            builder.append(templateContent, 0, serviceEndIndex);
            builder.append("\r\n");

            int data1 = templateContent.indexOf("@Resource") + 9;
            builder.append(templateContent, serviceEndIndex, data1);
            builder.append("\r\n");
            builder.append(templateContent.substring(data1).trim());
            codeUtil.createFile(codeUtil.getAdminProjectPath()
                    + "\\src\\main\\java\\cn\\tworice\\client\\service\\"
                    + createServerVO.getEntityName()
                    + "Service.java", builder.toString());
            log.info("生成Service文件成功");
        }catch (Exception exception){
            log.error(exception.getMessage());
            log.error("生成Service文件失败");
            return false;
        }

        return true;
    }

    @Override
    public boolean createDao(CreateServerVO createServerVO) {
        try{
            StringBuilder builder = new StringBuilder();
            String content = codeUtil.readByName("dao");
            content = content.replace(CodeGenConst.ENTITY_NAME, createServerVO.getEntityName());
            int data = content.indexOf("@Repository") + 11;
            builder.append(content, 0, data);
            builder.append("\r\n");
            builder.append(content.substring(data).trim());
            codeUtil.createFile(codeUtil.getAdminProjectPath() + "\\src\\main\\java\\cn\\tworice\\client\\dao\\" + createServerVO.getEntityName() + "Dao.java", builder.toString());
            log.info("生成Dao文件成功");
        }catch (Exception exception){
            exception.printStackTrace();
            log.error("生成Dao文件失败");
            return false;
        }

        return true;
    }

    /**
     * 使用MyBatisPlus后不生成XML
     */
    @Deprecated
    @Override
    public boolean createMapper(CreateServerVO createServerVO) {
        try{
            String content = codeUtil.readByName("mapper");
            content = content.replace("-tworice_name-", createServerVO.getEntityName());

            // 构建queryList和queryTotal条件语句
            StringBuilder queryListWhere = new StringBuilder();
            StringBuilder queryList = new StringBuilder();
            StringBuilder queryTotal = new StringBuilder();
            // TODO 多个表联查时构建
            StringBuilder queryListJoinTable = new StringBuilder("");

            // 构建insertSql
            StringBuilder insertSql = new StringBuilder();
            insertSql.append("INSERT INTO ");
            insertSql.append(createServerVO.getTableName());
            insertSql.append("(");

            // 构建insertList SQL
            StringBuilder insertList = new StringBuilder();
            insertList.append("INSERT INTO ");
            insertList.append(createServerVO.getTableName());
            insertList.append("(");

            // 构建update语句
            StringBuilder updateSql = new StringBuilder();
            updateSql.append("UPDATE ");
            updateSql.append(createServerVO.getTableName());
            updateSql.append("<trim prefix=\"SET\" prefixOverrides=\",\">");

            // 循环构建sql内容
            List<Parameter> fieldList = createServerVO.getFieldList();
            for(int i=0;i<fieldList.size();i++){
                // 字段名称 system_id等
                String field = fieldList.get(i).getField();
                // 字段名称转驼峰命名
                String fieldHump = StringUtils.lineToHump(field);

                insertSql.append(field);
                insertList.append(field);

                if(!"create_time".equals(field)){ // 如果该属性不是日期
                    // 开始拼接update语句
                    updateSql.append("<if test=\"");
                    updateSql.append(fieldHump);
                    updateSql.append("!=null\">,");
                    updateSql.append(field);
                    updateSql.append("=");
                    updateSql.append("#{");
                    updateSql.append(fieldHump);
                    updateSql.append("}");
                    updateSql.append("</if>");
                }

                // 构建queryList、queryTotal语句
                if(fieldList.get(i).getQuery()){ // 判断当前字段是否需要构建查询条件
                    queryListWhere.append("<if test=\"entity.").append(fieldHump).append("!=null\"> ");
                    queryTotal.append("<if test=\"").append(fieldHump).append("!=null\"> ");
                    // 判断查询条件
                    if("=".equals(fieldList.get(i).getQueryType()) || "字典".equals(fieldList.get(i).getQueryType())){
                        queryListWhere.append("AND a.").append(field).append(" = #{entity.").append(fieldHump).append("}");
                        queryTotal.append("AND a.").append(field).append(" = #{").append(fieldHump).append("}");
                    }else if("LIKE".equals(fieldList.get(i).getQueryType())){
                        queryListWhere.append("AND a.").append(field).append(" LIKE '%${entity.").append(fieldHump).append("}%'");
                        queryTotal.append("AND a.").append(field).append(" LIKE '%${").append(fieldHump).append("}%'");
                    } else if ("数据表".equals(fieldList.get(i).getQueryType())) {
                        queryListWhere.append("AND a.").append(field).append(" = #{entity.").append(fieldHump).append("}");
//                        queryListJoinTable.append("<if test=\"entity."+StringUtils.lineToHump(fieldList.get(i).getField())+"!=null\"> LEFT JOIN " + fieldList.get(i).getDict() + " b ");
//                        queryListJoinTable.append("ON a." + fieldList.get(i).getField() + "=b.id</if>");
                        queryTotal.append("AND a.").append(field).append(" = #{").append(fieldHump).append("}");
                    }
                    queryListWhere.append("</if>");
                    queryTotal.append("</if>");
                }
                // 如果当前是列表最后一个时
                if(i==fieldList.size()-1){
                    updateSql.append("</trim>");
                }else {
                    // 当前不是字段列表最后一个
                    insertSql.append(",");
                    insertList.append(",");
                }
            }

            // 构建SQL VALUE内容
            insertSql.append(") VALUE(");
            insertList.append(") VALUES");
            insertList.append("<foreach collection=\"list\" separator=\",\" item=\"item\">(");

            for(int i=0;i<fieldList.size();i++){
                insertSql.append("#{");
                insertList.append("#{item.");

                insertSql.append(StringUtils.lineToHump(fieldList.get(i).getField()));
                insertList.append(StringUtils.lineToHump(fieldList.get(i).getField()));

                if(i==fieldList.size()-1){
                    insertSql.append("}");
                    insertList.append("}");
                    continue;
                }

                insertSql.append("},");
                insertList.append("},");
            }
            insertSql.append(")");
            insertList.append(")</foreach>");

            content = content.replace("-tworice_insert_sql-", insertSql.toString());
            content = content.replace("-tworice_insert_list_sql-", insertList.toString());
            updateSql.append("\r\n WHERE id=#{id}");
            content = content.replace("-tworice_update_sql-", updateSql.toString());
            content = content.replace("-tworice_table_name-", createServerVO.getTableName());
            content = content.replace("-tworice_query_list_where-", queryListWhere.toString());
            content = content.replace("-tworice_query_total-", queryTotal.toString());
            content = content.replace("-tworice_join_table-", queryListJoinTable.toString());

            codeUtil.createFile(System.getProperty("user.dir") + "\\src\\main\\resources\\cn\\tworice\\client\\dao\\" + createServerVO.getEntityName() + "Dao.xml", content);
            log.info("生成Mapper文件成功");
        }catch (Exception exception){
            log.error("生成Mapper文件失败",exception);
            return false;
        }

        return true;
    }

    @Override
    public boolean createEntity(CreateServerVO createServerVO) {
        try {
            StringBuilder builder = new StringBuilder();
            String content = codeUtil.readByName("entity");// 通过模板名称读取模板内容
            content = content.replace(CodeGenConst.ENTITY_NAME, createServerVO.getEntityName());
            content = content.replace(CodeGenConst.TABLE_NAME, createServerVO.getTableName());

            // 在注解后加入换行符
            int data = content.indexOf("@Data") + 5;
            builder.append(content, 0, data);
            builder.append("\r\n");

            // 找到最后一个花括号，并将花括号前的内容保存起来
            int end = content.lastIndexOf("}");
            builder.append(content.substring(data, end).trim());
            builder.append("\r\n");
            // 在后面加入生成的内容
            List<Parameter> fieldList = createServerVO.getFieldList();
            fieldList.forEach(item -> {
                if(!this.ignoreField.contains(item.getField())){
                    builder.append("@ExcelProperty(\"");
                    builder.append(item.getName());
                    builder.append("\")\r\n");
                    builder.append("private ");
                    builder.append(item.getType()).append(" ");
                    builder.append(StringUtils.lineToHump(item.getField())).append(" ");
                    builder.append(";\r\n");
                }
            });
            builder.append("}");
            codeUtil.createFile(codeUtil.getAdminProjectPath() + "\\src\\main\\java\\cn\\tworice\\common\\entity\\code\\" + createServerVO.getEntityName() + ".java", builder.toString());
            log.info("生成实体类文件成功");
        }catch (Exception exception){
            log.error("生成实体类文件失败",exception);
            return false;
        }
        return true;
    }

    private String buildQuery(CreateServerVO createServerVO) {
        StringBuilder result = new StringBuilder();
        List<Parameter> fieldList = createServerVO.getFieldList();

        for (Parameter item : fieldList) {
            // 字段名称 system_id等
            String field = item.getField();
            // 字段名称转驼峰命名
            String fieldHump = StringUtils.lineToHump2(field);

            if ("create_time".equals(field) || "update_time".equals(field) || "creator".equals(field)) {
                continue;
            }
            // 构建queryList、queryTotal语句
            if (item.getQuery()) { // 判断当前字段是否需要构建查询条件
                result.append(".")
                        .append(this.getQueryType(item.getQueryType()))
                        .append("(")
                        .append(createServerVO.getEntityName())
                        .append("::get")
                        .append(fieldHump)
                        .append(",entity.get")
                        .append(fieldHump)
                        .append("())");
            }
        }
        return result.toString();
    }

    private String getQueryType(String queryType) {
        switch (queryType) {
            case "=":
            case "字典":
            case "数据表":
                return "eqIfPresent";
            case "LIKE":
                return "likeIfPresent";
            case "<":
                return "ltIfPresent";
            case "<=":
                return "leIfPresent";
            case ">":
                return "gtIfPresent";
            case ">=":
                return "geIfPresent";
            case "不等于":
                return "neIfPresent";
            default:
                log.error("当前版本目前不支持查询类型：" + queryType);
                return "";
        }
    }


}
